package com.test.config.shiro.realms;

import com.test.config.shiro.saltSerializable.MyByteSource;
import com.test.entity.Permission;
import com.test.entity.User;
import com.test.service.UserService;
import com.test.util.ApplicationContextUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.List;

/**
 * 自定义的realm
 */
public class MyCustomerRealm extends AuthorizingRealm {

    // @Autowired  private UserService userService;
    //此处使用一个自定义的获取spring中所有bean的工具类,获取到查询用户信息的接口bean

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("+++++++++++++++++++++进入自定的realm进行授权操作++++++++++++++++++++++++");
        //获取已经认证通过的用户信息
        String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
        System.out.println("用户信息 : " + primaryPrincipal);

        //调用获取所有bean的工具类,根据用户名查询当前用户的所有的角色信息,可以直接注入bean
        UserService userService = (UserService) ApplicationContextUtils.getBean("userService");
        User user = userService.findRolesByUserName(primaryPrincipal);
        System.out.println("用户角色信息 : " + user.getRoles());
        if (user.getRoles() != null) {
            //授权具体执行的类 ,将查询到的用户的角色信息,添加到shiro中
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            user.getRoles().forEach(role -> {
                simpleAuthorizationInfo.addRole(role.getRoleName());    //用户下多个角色信息遍历,交给shiro

                //根据认证的角色id,查询角色信息对应的多个权限信息
                List<Permission> perms= userService.findPermsByRoleId(role.getRId());
                perms.forEach(perm-> {
                    simpleAuthorizationInfo.addStringPermission(perm.getPermissionName()); //查询用户下每个角色对应的权限信息,交给shiro
                });
            });  //此处的角色信息应该是从数据库查询到的,也就是当前用户拥有的角色和权限  验证权限三种方式(1页面控制 2代码判断 3注解@RequestRole)
            //拥有/user下的 添加,查询,修改操作,无删除权限不显示
            return simpleAuthorizationInfo;  //将角色信息方会给shiro
        }
        return null;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("-------------------进入自定的realm进行认证操作-------------------------");
        //获取登录的token , 获取用户名信息
        String principal = (String) authenticationToken.getPrincipal();
        System.out.println("用户信息 : " + principal);
        //根据用户名.查询数据库中用户信息, 此处使用一个自定义的获取spring中所有bean的工具类,获取到查询用户信息的接口bean ----  ser user = userService.findUserByNmae(principal);
        UserService userService = (UserService) ApplicationContextUtils.getBean("userService");
        System.out.println("获取到的bean :" + userService);
        User user = userService.findUserByNmae(principal);
        if (user != null) {

            //认证具体执行的类
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                    user.getUsername(),   //数据库中用户名
                    user.getPassword(),  //数据库用户密码 msd5 + salt + 散次列(注册加了10次)  之后的
                    //ByteSource.Util.bytes(user.getSalt()),  // 加的盐
                    new MyByteSource(user.getSalt()),  // 自定义的salt的实现,实现了序列化接口,方便往redis中放
                    this.getName()   // 获取自定义的realm
            );
            return simpleAuthenticationInfo;  //需要在注入自定义的realm时,设置加密算法md5,散次列,盐在此处给了,shiro会自动识别
        }
        return null;
    }
}
